home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / Gnuplot / Source / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-02  |  11.6 KB  |  617 lines

  1. #ifndef lint
  2. static char    *RCSid = "$Id: parse.c%v 3.38.2.81 1993/02/24 02:29:34 woo Exp woo $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - parse.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley 
  9.  *
  10.  * Permission to use, copy, and distribute this software and its documentation
  11.  * for any purpose with or without fee is hereby granted, provided that the
  12.  * above copyright notice appear in all copies and that both that copyright
  13.  * notice and this permission notice appear in supporting documentation. 
  14.  *
  15.  * Permission to modify the software is granted, but not the right to distribute
  16.  * the modified code.  Modifications are to be distributed as patches to
  17.  * released version. 
  18.  *
  19.  * This software is provided "as is" without express or implied warranty. 
  20.  *
  21.  *
  22.  * AUTHORS 
  23.  *
  24.  * Original Software: Thomas Williams,  Colin Kelley. 
  25.  *
  26.  * Gnuplot 2.0 additions: Russell Lang, Dave Kotz, John Campbell. 
  27.  *
  28.  * Gnuplot 3.0 additions: Gershon Elber and many others. 
  29.  *
  30.  * Send your comments or suggestions to info-gnuplot@dartmouth.edu. This is
  31.  * a mailing list; to join it send a note to
  32.  * info-gnuplot-request@dartmouth.edu.  Send bug reports to
  33.  * bug-gnuplot@dartmouth.edu. 
  34.  */
  35.  
  36. #include <stdio.h>
  37. #include <setjmp.h>
  38. #include <signal.h>
  39. #include <errno.h>
  40. #include <math.h>
  41. #include "plot.h"
  42.  
  43. #ifndef vms
  44. #if !defined(__ZTC__) && !defined(__MSC__)
  45. extern int      errno;
  46. #endif
  47. #endif
  48.  
  49. extern int      num_tokens, c_token;
  50. extern struct lexical_unit token[];
  51. extern char     c_dummy_var[MAX_NUM_VAR][MAX_ID_LEN + 1];    /* name of current dummy
  52.                                  * vars */
  53. extern struct udft_entry *dummy_func;    /* pointer to dummy variable's func */
  54.  
  55. struct value   *
  56. pop(), *Ginteger(), *Gcomplex();
  57. struct at_type *
  58. temp_at(), *perm_at();
  59. struct udft_entry *add_udf();
  60. struct udvt_entry *add_udv();
  61. union argument *add_action();
  62.  
  63. struct at_type  at;
  64. #ifdef _Windows
  65. static jmp_buf far fpe_env;
  66. #else
  67. static jmp_buf  fpe_env;
  68. #endif
  69.  
  70. #define dummy (struct value *) 0
  71.  
  72. #if defined(__TURBOC__) || defined(DJGPP)
  73. void
  74. fpe()
  75. #else
  76. #if defined( __ZTC__ ) || defined( _CRAY ) || defined( sgi )|| defined( OS2 ) || defined(__EMX__)
  77. void
  78. fpe(an_int)
  79.     int             an_int;
  80. #else
  81. #ifdef NEXT
  82. void
  83. fpe(int an_int)
  84. #else
  85. #ifdef sgi
  86. void
  87. fpe(int sig, int code, struct sigcontext * sc)
  88. /*
  89.  * void fpe(an_int) int an_int; 
  90.  */
  91. #else
  92. fpe()
  93. #endif
  94. #endif
  95. #endif                /* __ZTC__ || _CRAY */
  96. #endif                /* __TURBOC__ */
  97. {
  98. #if defined(MSDOS) && !defined(__EMX__) && !defined(DJGPP) && !defined(_Windows) || defined(DOS386)
  99.     /* thanks to lotto@wjh12.UUCP for telling us about this  */
  100.     _fpreset();
  101. #endif
  102. #if defined(MSDOS) && defined(__EMX__)
  103.     (void)signal(SIGFPE, (void *)fpe);
  104. #else
  105. #ifdef DJGPP
  106.     (void)signal(SIGFPE, (SignalHandler)fpe);
  107. #else
  108. #ifdef OS2
  109.     (void) signal(an_int, SIG_ACK);
  110. #else
  111.     (void)signal(SIGFPE, fpe);
  112. #endif
  113. #endif
  114. #endif
  115. #ifdef ATARI
  116.     /* do we need this ? (AL) */
  117.     fprintf(stderr, "floating point exception!\n");
  118. #endif
  119.     undefined = TRUE;
  120.     longjmp(fpe_env, TRUE);
  121. }
  122.  
  123.  
  124. #ifdef apollo
  125. #include <apollo/base.h>
  126. #include <apollo/pfm.h>
  127. #include <apollo/fault.h>
  128.  
  129. /*
  130.  * On an Apollo, the OS can signal a couple errors that are not mapped into
  131.  * SIGFPE, namely signalling NaN and branch on an unordered comparison.  I
  132.  * suppose there are others, but none of these are documented, so I handle
  133.  * them as they arise. 
  134.  *
  135.  * Anyway, we need to catch these faults and signal SIGFPE. 
  136.  */
  137.  
  138. pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t & fault_rec)
  139. {
  140.     kill(getpid(), SIGFPE);
  141.     return pfm_$continue_fault_handling;
  142. }
  143.  
  144. apollo_pfm_catch()
  145. {
  146.     status_$t status;
  147.     pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
  148.                        apollo_sigfpe, &status);
  149.     pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
  150.                        apollo_sigfpe, &status);
  151. }
  152. #endif
  153.  
  154.  
  155. evaluate_at(at_ptr, val_ptr)
  156.     struct at_type *at_ptr;
  157.     struct value   *val_ptr;
  158. {
  159.     double          temp, real();
  160.  
  161.     undefined = FALSE;
  162.     errno = 0;
  163.     reset_stack();
  164.  
  165. #ifndef DOSX286
  166.     if (setjmp(fpe_env))
  167.         return(0);        /* just bail out */
  168. #if defined(MSDOS) && defined(__EMX__)
  169.     (void)signal(SIGFPE, (void *)fpe);
  170. #else
  171. #if DJGPP
  172.     (void)signal(SIGFPE, (SignalHandler)fpe);
  173. #else
  174.     (void)signal(SIGFPE, fpe);    /* catch core dumps on FPEs */
  175. #endif
  176. #endif
  177. #endif
  178.  
  179.     execute_at(at_ptr);
  180.  
  181. #ifndef DOSX286
  182.     (void)signal(SIGFPE, SIG_DFL);
  183. #endif
  184.  
  185.     if (errno == EDOM || errno == ERANGE) {
  186.         undefined = TRUE;
  187.     } else {
  188.         (void)pop(val_ptr);
  189.         check_stack();
  190.     }
  191.     /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
  192.     temp = real(val_ptr);
  193.     if (temp > VERYLARGE || temp < -VERYLARGE) {
  194.         undefined = TRUE;
  195.     }
  196. }
  197.  
  198.  
  199. struct value   *
  200. const_express(valptr)
  201.     struct value   *valptr;
  202. {
  203.     register int    tkn = c_token;
  204.     if (END_OF_COMMAND)
  205.         int_error("constant expression required", c_token);
  206.     evaluate_at(temp_at(), valptr);    /* run it and send answer back */
  207.     if (undefined) {
  208.         int_error("undefined value", tkn);
  209.     }
  210.     return (valptr);
  211. }
  212.  
  213.  
  214. struct at_type *
  215. temp_at()
  216. {                /* build a static action table and return its
  217.                  * pointer */
  218.     at.a_count = 0;        /* reset action table !!! */
  219.     express();
  220.     return (&at);
  221. }
  222.  
  223.  
  224. /* build an action table, put it in dynamic memory, and return its pointer */
  225.  
  226. struct at_type *
  227. perm_at()
  228. {
  229.     register struct at_type *at_ptr;
  230.     register unsigned int len;
  231.  
  232.     (void)temp_at();
  233.     len = sizeof(struct at_type) -
  234.         (MAX_AT_LEN - at.a_count) * sizeof(struct at_entry);
  235.     at_ptr = (struct at_type *) alloc((unsigned long)len, "action table");
  236.     (void)memcpy(at_ptr, &at, len);
  237.     return (at_ptr);
  238. }
  239.  
  240.  
  241. #ifdef NOCOPY
  242. /*
  243.  * cheap and slow version of memcpy() in case you don't have one 
  244.  */
  245. memcpy(dest, src, len)
  246.     char           *dest, *src;
  247.     unsigned int    len;
  248. {
  249.     while (len--)
  250.         *dest++ = *src++;
  251. }
  252. #endif                /* NOCOPY */
  253.  
  254.  
  255. express()
  256. {                /* full expressions */
  257.     xterm();
  258.     xterms();
  259. }
  260.  
  261. xterm()
  262. {                /* ? : expressions */
  263.     aterm();
  264.     aterms();
  265. }
  266.  
  267.  
  268. aterm()
  269. {
  270.     bterm();
  271.     bterms();
  272. }
  273.  
  274.  
  275. bterm()
  276. {
  277.     cterm();
  278.     cterms();
  279. }
  280.  
  281.  
  282. cterm()
  283. {
  284.     dterm();
  285.     dterms();
  286. }
  287.  
  288.  
  289. dterm()
  290. {
  291.     eterm();
  292.     eterms();
  293. }
  294.  
  295.  
  296. eterm()
  297. {
  298.     fterm();
  299.     fterms();
  300. }
  301.  
  302.  
  303. fterm()
  304. {
  305.     gterm();
  306.     gterms();
  307. }
  308.  
  309.  
  310. gterm()
  311. {
  312.     hterm();
  313.     hterms();
  314. }
  315.  
  316.  
  317. hterm()
  318. {
  319.     unary();        /* - things */
  320.     iterms();        /* * / % */
  321. }
  322.  
  323.  
  324. factor()
  325. {
  326.     register int    value;
  327.  
  328.     if (equals(c_token, "(")) {
  329.         c_token++;
  330.         express();
  331.         if (!equals(c_token, ")"))
  332.             int_error("')' expected", c_token);
  333.         c_token++;
  334.     } else if (isnumber(c_token)) {
  335.         convert(&(add_action(PUSHC)->v_arg), c_token);
  336.         c_token++;
  337.     } else if (isletter(c_token)) {
  338.         if ((c_token + 1 < num_tokens) && equals(c_token + 1, "(")) {
  339.             value = standard(c_token);
  340.             if (value) {    /* it's a standard function */
  341.                 c_token += 2;
  342.                 express();
  343.                 if (equals(c_token, ",")) {
  344.                     while (equals(c_token, ",")) {
  345.                         c_token += 1;
  346.                         express();
  347.                     }
  348.                 }
  349.                 if (!equals(c_token, ")"))
  350.                     int_error("')' expected", c_token);
  351.                 c_token++;
  352.                 (void)add_action(value);
  353.             } else {
  354.                 int             call_type = (int)CALL;
  355.                 value = c_token;
  356.                 c_token += 2;
  357.                 express();
  358.                 if (equals(c_token, ",")) {
  359.                     struct value    num_params;
  360.                     num_params.type = INTGR;
  361.                     num_params.v.int_val = 1;
  362.                     while (equals(c_token, ",")) {
  363.                         num_params.v.int_val += 1;
  364.                         c_token += 1;
  365.                         express();
  366.                     }
  367.                     add_action(PUSHC)->v_arg = num_params;
  368.                     call_type = (int)CALLN;
  369.                 }
  370.                 if (!equals(c_token, ")"))
  371.                     int_error("')' expected", c_token);
  372.                 c_token++;
  373.                 add_action(call_type)->udf_arg = add_udf(value);
  374.             }
  375.         } else {
  376.             if (equals(c_token, c_dummy_var[0])) {
  377.                 c_token++;
  378.                 add_action(PUSHD1)->udf_arg = dummy_func;
  379.             } else if (equals(c_token, c_dummy_var[1])) {
  380.                 c_token++;
  381.                 add_action(PUSHD2)->udf_arg = dummy_func;
  382.             } else {
  383.                 int             i, param = 0;
  384.                 for (i = 2; i < MAX_NUM_VAR; i++) {
  385.                     if (equals(c_token, c_dummy_var[i])) {
  386.                         struct value    num_params;
  387.                         num_params.type = INTGR;
  388.                         num_params.v.int_val = i;
  389.                         param = 1;
  390.                         c_token++;
  391.                         add_action(PUSHC)->v_arg = num_params;
  392.                         add_action(PUSHD)->udf_arg = dummy_func;
  393.                         break;
  394.                     }
  395.                 }
  396.                 if (!param) {    /* defined variable */
  397.                     add_action(PUSH)->udv_arg = add_udv(c_token);
  398.                     c_token++;
  399.                 }
  400.             }
  401.         }
  402.     }
  403.     /* end if letter */
  404.     else
  405.         int_error("invalid expression ", c_token);
  406.  
  407.     /* add action code for ! (factorial) operator */
  408.     while (equals(c_token, "!")) {
  409.         c_token++;
  410.         (void)add_action(FACTORIAL);
  411.     }
  412.     /* add action code for ** operator */
  413.     if (equals(c_token, "**")) {
  414.         c_token++;
  415.         unary();
  416.         (void)add_action(POWER);
  417.     }
  418. }
  419.  
  420.  
  421.  
  422. xterms()
  423. {                /* create action code for ? : expressions */
  424.  
  425.     if (equals(c_token, "?")) {
  426.         register int    savepc1, savepc2;
  427.         register union argument *argptr1, *argptr2;
  428.         c_token++;
  429.         savepc1 = at.a_count;
  430.         argptr1 = add_action(JTERN);
  431.         express();
  432.         if (!equals(c_token, ":"))
  433.             int_error("expecting ':'", c_token);
  434.         c_token++;
  435.         savepc2 = at.a_count;
  436.         argptr2 = add_action(JUMP);
  437.         argptr1->j_arg = at.a_count - savepc1;
  438.         express();
  439.         argptr2->j_arg = at.a_count - savepc2;
  440.     }
  441. }
  442.  
  443.  
  444. aterms()
  445. {                /* create action codes for || operator */
  446.  
  447.     while (equals(c_token, "||")) {
  448.         register int    savepc;
  449.         register union argument *argptr;
  450.         c_token++;
  451.         savepc = at.a_count;
  452.         argptr = add_action(JUMPNZ);    /* short-circuit if already
  453.                          * TRUE */
  454.         aterm();
  455.         argptr->j_arg = at.a_count - savepc;    /* offset for jump */
  456.         (void)add_action(BOOLE);
  457.     }
  458. }
  459.  
  460.  
  461. bterms()
  462. {                /* create action code for && operator */
  463.  
  464.     while (equals(c_token, "&&")) {
  465.         register int    savepc;
  466.         register union argument *argptr;
  467.         c_token++;
  468.         savepc = at.a_count;
  469.         argptr = add_action(JUMPZ);    /* short-circuit if already
  470.                          * FALSE */
  471.         bterm();
  472.         argptr->j_arg = at.a_count - savepc;    /* offset for jump */
  473.         (void)add_action(BOOLE);
  474.     }
  475. }
  476.  
  477.  
  478. cterms()
  479. {                /* create action code for | operator */
  480.  
  481.     while (equals(c_token, "|")) {
  482.         c_token++;
  483.         cterm();
  484.         (void)add_action(BOR);
  485.     }
  486. }
  487.  
  488.  
  489. dterms()
  490. {                /* create action code for ^ operator */
  491.  
  492.     while (equals(c_token, "^")) {
  493.         c_token++;
  494.         dterm();
  495.         (void)add_action(XOR);
  496.     }
  497. }
  498.  
  499.  
  500. eterms()
  501. {                /* create action code for & operator */
  502.  
  503.     while (equals(c_token, "&")) {
  504.         c_token++;
  505.         eterm();
  506.         (void)add_action(BAND);
  507.     }
  508. }
  509.  
  510.  
  511. fterms()
  512. {                /* create action codes for == and !=
  513.                  * operators */
  514.  
  515.     while (TRUE) {
  516.         if (equals(c_token, "==")) {
  517.             c_token++;
  518.             fterm();
  519.             (void)add_action(EQ);
  520.         } else if (equals(c_token, "!=")) {
  521.             c_token++;
  522.             fterm();
  523.             (void)add_action(NE);
  524.         } else
  525.             break;
  526.     }
  527. }
  528.  
  529.  
  530. gterms()
  531. {                /* create action code for < > >= or <=
  532.                  * operators */
  533.  
  534.     while (TRUE) {
  535.         /* I hate "else if" statements */
  536.         if (equals(c_token, ">")) {
  537.             c_token++;
  538.             gterm();
  539.             (void)add_action(GT);
  540.         } else if (equals(c_token, "<")) {
  541.             c_token++;
  542.             gterm();
  543.             (void)add_action(LT);
  544.         } else if (equals(c_token, ">=")) {
  545.             c_token++;
  546.             gterm();
  547.             (void)add_action(GE);
  548.         } else if (equals(c_token, "<=")) {
  549.             c_token++;
  550.             gterm();
  551.             (void)add_action(LE);
  552.         } else
  553.             break;
  554.     }
  555.  
  556. }
  557.  
  558.  
  559.  
  560. hterms()
  561. {                /* create action codes for + and - operators */
  562.  
  563.     while (TRUE) {
  564.         if (equals(c_token, "+")) {
  565.             c_token++;
  566.             hterm();
  567.             (void)add_action(PLUS);
  568.         } else if (equals(c_token, "-")) {
  569.             c_token++;
  570.             hterm();
  571.             (void)add_action(MINUS);
  572.         } else
  573.             break;
  574.     }
  575. }
  576.  
  577.  
  578. iterms()
  579. {                /* add action code for * / and % operators */
  580.  
  581.     while (TRUE) {
  582.         if (equals(c_token, "*")) {
  583.             c_token++;
  584.             unary();
  585.             (void)add_action(MULT);
  586.         } else if (equals(c_token, "/")) {
  587.             c_token++;
  588.             unary();
  589.             (void)add_action(DIV);
  590.         } else if (equals(c_token, "%")) {
  591.             c_token++;
  592.             unary();
  593.             (void)add_action(MOD);
  594.         } else
  595.             break;
  596.     }
  597. }
  598.  
  599.  
  600. unary()
  601. {                /* add code for unary operators */
  602.     if (equals(c_token, "!")) {
  603.         c_token++;
  604.         unary();
  605.         (void)add_action(LNOT);
  606.     } else if (equals(c_token, "~")) {
  607.         c_token++;
  608.         unary();
  609.         (void)add_action(BNOT);
  610.     } else if (equals(c_token, "-")) {
  611.         c_token++;
  612.         unary();
  613.         (void)add_action(UMINUS);
  614.     } else
  615.         factor();
  616. }
  617.